第十八天,你已經成功完成了第一個 MVVM 專案,並體驗了 ViewModel
如何解決螢幕旋轉時資料流失的問題。
但你可能會發現,在 MainActivity
中,每次點擊按鈕後,我們還是需要手動地呼叫 setText()
來更新 TextView
。
如果我們希望 View
能夠自動感知到 ViewModel
裡面的資料有變化,然後自動更新畫面,該怎麼辦呢?這時,我們就需要今天的終極武器:LiveData
。
LiveData
?LiveData
就是一個 「有魔法的包裹」。
View
,就像是一個「觀察者」,它會一直盯著這個包裹。只要包裹裡面的資料一變,View
就會立刻更新畫面。LiveData
裡的資料改變時,它會自動通知所有觀察者。LiveData
知道 Activity
的生命週期。它只會向處於活躍狀態的 View
(例如:畫面正在顯示) 發送通知,避免記憶體洩漏。今天,我們要修改昨天的計數器 App,用 LiveData
來實現畫面的自動更新。
CounterViewModel.java
打開你的「智慧助理」檔案 CounterViewModel.java
。我們要將原本的 int counter
改成 LiveData
。
`import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; // 新增匯入 MutableLiveData
import androidx.lifecycle.ViewModel;
public class CounterViewModel extends ViewModel {
// 這是我們「智慧助理」要管理的資料,使用 MutableLiveData
private MutableLiveData<Integer> _counter = new MutableLiveData<>();
// 這是給 View 觀察的公開版本
public LiveData<Integer> counter = _counter;
// 建構子,設定初始值
public CounterViewModel() {
_counter.setValue(0);
}
// 增加數字的方法
public void incrementCounter() {
// 從包裹中取出舊值
int currentValue = _counter.getValue() != null ? _counter.getValue() : 0;
// 增加後,再把新值設定回包裹
_counter.setValue(currentValue + 1);
}
}
MutableLiveData
:這是一個可以改變資料的 LiveData
版本。我們用它來修改計數器的值。LiveData
:這是一個只讀的 LiveData
版本。我們將它公開給 View
觀察,這樣 View
只能看,不能直接修改資料,保證了資料的安全。_counter.setValue(...)
:這是改變 LiveData
裡面資料的方法。MainActivity.java
(View)打開你的「被動」角色檔案 MainActivity.java
。這次,我們不再需要手動更新 TextView
了。
`import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.Observer; // 新增匯入 Observer
public class MainActivity extends AppCompatActivity {
private CounterViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1. 取得 ViewModel 實例
viewModel = new ViewModelProvider(this).get(CounterViewModel.class);
// 2. 找到 View 元件
TextView counterTextView = findViewById(R.id.counterTextView);
Button incrementButton = findViewById(R.id.incrementButton);
// 3. 讓 View 開始「觀察」ViewModel 的資料
viewModel.counter.observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer newCounterValue) {
// 當 ViewModel 裡的數字改變時,這裡的程式碼會自動執行
// 我們只需要在這裡更新畫面即可
counterTextView.setText(String.valueOf(newCounterValue));
}
});
// 4. 設定按鈕點擊事件
incrementButton.setOnClickListener(v -> {
// 點擊後,我們只需要告訴 ViewModel 執行邏輯
// 不用手動更新 View 了!
viewModel.incrementCounter();
});
}
}
viewModel.counter.observe(...)
:這就是讓 View
成為「觀察者」的關鍵程式碼。它會盯著 viewModel.counter
這個「包裹」。onChanged(...)
:當 counter
的值發生改變時,這個方法會自動被呼叫,並把新值傳進來。我們只需要在這裡更新 TextView
即可。MainActivity
的程式碼,你會發現我們在按鈕點擊事件裡,沒有任何一行更新畫面的程式碼!這就是 LiveData
的強大之處。今天我們成功地將 LiveData
應用在 MVVM
模式中,我們學會了:
LiveData
是什麼,以及它如何讓 View
自動觀察資料變化。ViewModel
中使用 MutableLiveData
來管理可變的資料。View
中使用 observe()
方法來觀察 LiveData
。你已經掌握了 MVVM
的核心精髓!從明天開始,我們將進入一個更進階的挑戰,讓你將這些概念應用在更複雜的 App 中!
明天見!